package com.mask.im.business.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.serializer.SerializerFeature;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.mask.im.business.common.constant.CommonConstant;
import com.mask.im.business.common.constant.WebSocketConstant;
import com.mask.im.business.mapper.IMGroupChatMapper;
import com.mask.im.business.mapper.IMGroupChatMessageMapper;
import com.mask.im.business.model.dto.GroupChatMessageDTO;
import com.mask.im.business.model.dto.AdminGroupChatMessageDTO;
import com.mask.im.business.common.model.PageResult;
import com.mask.im.business.common.model.RestResponse;
import com.mask.im.business.model.dto.GroupSendMessageDTO;
import com.mask.im.business.model.entity.UserInfo;
import com.mask.im.business.model.entity.chat.IMGroupChatDO;
import com.mask.im.business.model.entity.chat.IMGroupChatMessageDO;
import com.mask.im.business.model.entity.chat.IMGroupChatUserDO;
import com.mask.im.business.service.IMGroupChatMessageService;
import com.mask.im.business.service.IMGroupChatUserService;
import com.mask.im.business.common.util.PageUtil;
import com.mask.im.business.common.model.IMSendMessage;
import com.mask.im.business.service.UserInfoService;
import com.mask.im.sdk.dto.IMPushMessage;
import com.mask.im.sdk.enums.MessagePushTypeEnum;
import com.mask.im.sdk.service.MessagePushService;
import com.mask.token.util.MaskSecurityUtil;
import io.netty.channel.Channel;
import io.netty.handler.codec.http.websocketx.TextWebSocketFrame;
import lombok.SneakyThrows;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.thymeleaf.util.StringUtils;

import javax.annotation.Resource;
import java.util.*;
import java.util.concurrent.CompletableFuture;
import java.util.stream.Collectors;


/**
 * 群聊记录管理
 *
 * @author jian
 */
@Service
public class IMGroupChatMessageServiceImpl extends ServiceImpl<IMGroupChatMessageMapper, IMGroupChatMessageDO> implements IMGroupChatMessageService {

    @Resource
    private IMGroupChatUserService groupChatUserService;

    @Resource
    private IMGroupChatMapper groupChatMapper;

    @Resource
    private MessagePushService pushService;

    @Resource
    private UserInfoService userInfoService;

    @Override
    public RestResponse<?> getGroupChatMessage(Long groupChatId) {
        Long userId = MaskSecurityUtil.getCurrentUserId();
        //判断用户是否在群聊中
        IMGroupChatUserDO imGroupChatUser = groupChatUserService.getByUserId(userId, groupChatId);
        if (Objects.isNull(imGroupChatUser)) {
            return RestResponse.fail("您未加入过该群聊或已彻底删除，请刷新页面");
        }

        //获取退出前的聊天记录
        if (imGroupChatUser.getMemberStatus().equals(0) && imGroupChatUser.getQuitTime() == null) {
            return RestResponse.fail("您正在申请该群聊当中，请耐心等候");
        }

        //获取聊天前的记录
        if ((imGroupChatUser.getMemberStatus().equals(0) && imGroupChatUser.getQuitTime() != null) || imGroupChatUser.getMemberStatus().equals(2)) {
            List<GroupChatMessageDTO> groupChatMessageDTOS = this.baseMapper.getBeforeLeaveGroupChatMessage(imGroupChatUser.getGroupId(), imGroupChatUser.getQuitTime());
            List<GroupChatMessageDTO> chatMessageDTOS = groupChatMessageDTOS.stream()
                    .filter((item) -> item.getDeletedBy() == null || !Arrays.asList(item.getDeletedBy().split(",")).contains(userId.toString()))
                    .peek((item) -> {
                        item.setGroupChatId(imGroupChatUser.getGroupId());
                        item.setIsMyselfMessage(item.getMemberId().equals(userId));
                    }).collect(Collectors.toList());
            return RestResponse.ok(chatMessageDTOS);
        }

        if (imGroupChatUser.getMemberStatus().equals(1)) {
            List<GroupChatMessageDTO> groupChatMessageDTOS = this.baseMapper.getLeaveGroupChatMessage(imGroupChatUser.getGroupId());
            List<GroupChatMessageDTO> chatMessageDTOS = groupChatMessageDTOS.stream()
                    .filter((item) -> item.getDeletedBy() == null || !Arrays.asList(item.getDeletedBy().split(",")).contains(userId.toString()))
                    .peek((item) -> {
                        item.setGroupChatId(imGroupChatUser.getGroupId());
                        item.setIsMyselfMessage(item.getMemberId().equals(userId));
                    }).collect(Collectors.toList());
            return RestResponse.ok(chatMessageDTOS);
        }
        return RestResponse.ok();
    }

    @Override
    @Transactional
    public RestResponse<String> clearGroupChatMessage(Long groupChatId) {
        Long userInfoId = MaskSecurityUtil.getCurrentUserId();
        List<IMGroupChatMessageDO> groupChatMessages = this.baseMapper.getVisibleRecords(groupChatId, userInfoId);
        if (null == groupChatMessages || groupChatMessages.isEmpty()) {
            return RestResponse.ok("已经没有多余的记录清空了");
        }
        List<IMGroupChatMessageDO> chatMessages = groupChatMessages.stream().peek(item -> {
            if (item.getDeletedUserIds() != null) {
                List<String> userInfoIdList = Arrays.asList(item.getDeletedUserIds().split(","));
                ArrayList<String> reBuildUserInfoIdList = new ArrayList<>(userInfoIdList);
                reBuildUserInfoIdList.add(userInfoId.toString());
                String userInfoIdJoin = StringUtils.join(reBuildUserInfoIdList, ",");
                item.setDeletedUserIds(userInfoIdJoin);
            } else {
                ArrayList<String> arrayList = new ArrayList<>(1);
                arrayList.add(userInfoId.toString());
                item.setDeletedUserIds(StringUtils.join(arrayList, ","));
            }
        }).collect(Collectors.toList());

        if (this.updateBatchById(chatMessages)) {
            return RestResponse.ok("已清空");
        } else {
            return RestResponse.fail("清空失败");
        }

    }

    @SneakyThrows
    @Override
    public PageResult<AdminGroupChatMessageDTO> groupChatMessage(String createTime, String groupChatName) {
        CompletableFuture<Integer> groupChatMessageCount = CompletableFuture.supplyAsync(() -> this.baseMapper.groupChatListCount(groupChatName, createTime));
        List<AdminGroupChatMessageDTO> chatListDTOList = this.baseMapper.groupChatMessage(groupChatName, createTime, PageUtil.getCurrentPage(), PageUtil.getSize());
        return PageResult.<AdminGroupChatMessageDTO>builder().data(chatListDTOList).total(groupChatMessageCount.get()).build();
    }

    @Override
    public RestResponse<IMGroupChatMessageDO> sendMessage(GroupSendMessageDTO sendMessageDTO) {
        Long groupChatId = sendMessageDTO.getGroupChatId();
        String content = (String) sendMessageDTO.getContent();
        Integer extend = sendMessageDTO.getMessageType();
        Long userId = MaskSecurityUtil.getCurrentUserId();
        //判断群聊是否使用中
        IMGroupChatDO groupChatDO = groupChatMapper.selectById(groupChatId);
        boolean flag = true;
        if (groupChatDO.getStatus().equals(CommonConstant.ONE)) {
            flag = false;
        }

        //保存聊天记录
        IMGroupChatMessageDO chatMessageDO = IMGroupChatMessageDO.builder()
                .content(content)
                .groupId(groupChatId)
                .isDeleted(0)
                .messageType(0)
                .sendStatus(flag ? 1 : 0)
                .systemPrompt(flag ? "" : "群聊已被解散，消息发送失败")
                .senderId(userId)
                .messageType(extend).build();
        this.baseMapper.insert(chatMessageDO);

        //todo 刷新群聊最新消息(最新的应该在chatList表中)
        IMGroupChatDO imGroupChat = IMGroupChatDO.builder()
                .recentTime(new Date())
                .id(groupChatId)
                .recentMessage(content).build();
        groupChatMapper.updateById(imGroupChat);


        //获取插入的消息
        GroupChatMessageDTO groupChatMessageDTO = getGroupChatMessageDTO(chatMessageDO);

        //获取当前加入该群聊的在线人的id
        List<IMGroupChatUserDO> imGroupChatUsers = groupChatUserService.list(new LambdaQueryWrapper<IMGroupChatUserDO>()
                .select(IMGroupChatUserDO::getUserId, IMGroupChatUserDO::getId, IMGroupChatUserDO::getUnreadCount)
                .eq(IMGroupChatUserDO::getGroupId, groupChatId));
        List<Long> imGroupChatUserIds = imGroupChatUsers.stream().map(IMGroupChatUserDO::getUserId).collect(Collectors.toList());
        groupChatMessageDTO.setIsMyselfMessage(true);

        IMPushMessage<IMGroupChatMessageDO> pushMessage = new IMPushMessage<>();
        pushMessage.setSenderId(userId);
        pushMessage.setReceiversId(imGroupChatUserIds);
        pushMessage.setPushType(MessagePushTypeEnum.GROUP_MESSAGE.type());
        pushMessage.setGroupId(groupChatId);
        pushMessage.setContent(chatMessageDO);
        List<Long> offlineUserIds = pushService.pushGroupMessage(pushMessage);

        imGroupChatUsers.stream().filter(item -> offlineUserIds.contains(item.getUserId()))
                .forEach(groupChatUser -> {
                    Long infoId = groupChatUser.getUserId();
                    Boolean online = pushService.isOnline(infoId);
                    if (!online) {
                        groupChatUser.setId(groupChatUser.getId());
                        groupChatUser.setUnreadCount(groupChatUser.getUnreadCount() + 1);
                        groupChatUserService.updateById(groupChatUser);
                    }
                });
        return RestResponse.ok(chatMessageDO);
    }

    private GroupChatMessageDTO getGroupChatMessageDTO(IMGroupChatMessageDO chatMessage) {
        IMGroupChatUserDO imGroupChatUser = groupChatUserService.getOne(new LambdaQueryWrapper<IMGroupChatUserDO>()
                .eq(IMGroupChatUserDO::getGroupId, chatMessage.getGroupId())
                .eq(IMGroupChatUserDO::getUserId, chatMessage.getSenderId()));
        UserInfo userInfo = userInfoService.getById(chatMessage.getSenderId());
        GroupChatMessageDTO groupChatMessageDTO = new GroupChatMessageDTO();
        groupChatMessageDTO.setGroupChatMessageId(chatMessage.getId());
        groupChatMessageDTO.setGroupChatId(chatMessage.getGroupId());
        groupChatMessageDTO.setMemberId(chatMessage.getSenderId());
        groupChatMessageDTO.setIsRetracted(chatMessage.getIsDeleted());
        groupChatMessageDTO.setContent(chatMessage.getContent());
        groupChatMessageDTO.setMessageType(chatMessage.getMessageType());
        groupChatMessageDTO.setIsSendSuccessfully(chatMessage.getSendStatus());
        groupChatMessageDTO.setMemberAvatar(userInfo.getAvatar());
        groupChatMessageDTO.setUsername(userInfo.getUsername());
        groupChatMessageDTO.setCustomizeRemark(imGroupChatUser.getCustomNickname());
        groupChatMessageDTO.setDeletedBy(chatMessage.getDeletedUserIds());
        groupChatMessageDTO.setCreateTime(chatMessage.getCreateTime());
        groupChatMessageDTO.setIsRetracted(chatMessage.getIsDeleted());
        return groupChatMessageDTO;
    }
}

